package com.bhkj.pdjhforotherapp.core.printutilspjq;

import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.Handler;
import android.os.Message;

import com.bhkj.pdjhforotherapp.R;
import com.bhkj.pdjhforotherapp.app.App;
import com.bhkj.pdjhforotherapp.common.bean.JhResultBean;
import com.bhkj.pdjhforotherapp.common.utils.Tools;
import com.bhkj.pdjhforotherapp.core.printutilspdj.Utils;
import com.blankj.utilcode.util.ActivityUtils;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.ToastUtils;

import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static android.hardware.usb.UsbManager.ACTION_USB_DEVICE_ATTACHED;
import static android.hardware.usb.UsbManager.ACTION_USB_DEVICE_DETACHED;
import static com.bhkj.pdjhforotherapp.core.printutilspjq.Constant.ACTION_USB_PERMISSION;
import static com.bhkj.pdjhforotherapp.core.printutilspjq.Constant.CONN_STATE_DISCONN;
import static com.bhkj.pdjhforotherapp.core.printutilspjq.DeviceConnFactoryManager.ACTION_QUERY_PRINTER_STATE;
import static com.bhkj.pdjhforotherapp.core.printutilspjq.DeviceConnFactoryManager.CONN_STATE_FAILED;
import static com.blankj.utilcode.util.StringUtils.getString;

/**
 * 评价器上插usb热敏打印设备 打印管理器
 */
public class PrintManagerPjq {
    private boolean isRegister = false;
    private static final int CONN_PRINTER = 0x12;
    /**
     * ESC查询打印机实时状态指令
     */
    private byte[] esc = {0x10, 0x04, 0x02};
    /**
     * CPCL查询打印机实时状态指令
     */
    private byte[] cpcl = {0x1b, 0x68};
    /**
     * TSC查询打印机状态指令
     */
    private byte[] tsc = {0x1b, '!', '?'};
    /**
     * 使用打印机指令错误
     */
    private static final int PRINTER_COMMAND_ERROR = 0x008;
    private UsbManager manager;
    private int id = 0;
    private ThreadPool threadPool;
    private ExecutorService executorService;

    private PrintManagerPjq() {
        if (executorService == null) {
            executorService = Executors.newCachedThreadPool();

        }
    }

    public static class Holder {
        static PrintManagerPjq INSTANCE = new PrintManagerPjq();
    }

    public static PrintManagerPjq getInstance() {
        return Holder.INSTANCE;
    }


    /**
     * 注册广播
     * Registration broadcast
     */
    public void registerBroadcast(Context context) {
        if (!isRegister) {
            isRegister = true;
            IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);//USB访问权限广播
            filter.addAction(ACTION_USB_DEVICE_DETACHED);//USB线拔出
            filter.addAction(ACTION_QUERY_PRINTER_STATE);//查询打印机缓冲区状态广播，用于一票一控
            filter.addAction(DeviceConnFactoryManager.ACTION_CONN_STATE);//与打印机连接状态
            filter.addAction(ACTION_USB_DEVICE_ATTACHED);//USB线插入
            context.registerReceiver(receiver, filter);
        }

    }

    /**
     * 检测usb设备进行连接
     */
    public void connectPrintDevice() {
        if (manager == null) {
            manager = (UsbManager) Tools.getApplicationByReflect().getSystemService(Context.USB_SERVICE);
        }
        // Get the list of attached devices
        HashMap<String, UsbDevice> devices = manager.getDeviceList();
        Iterator<UsbDevice> deviceIterator = devices.values().iterator();
        int count = devices.size();
        LogUtils.d("count " + count);
        if (count > 0) {
            while (deviceIterator.hasNext()) {
                UsbDevice device = deviceIterator.next();
                String devicename = device.getDeviceName();
                connectByJugde(manager, devicename);
            }
        } else {
            ToastUtils.showShort("未检测到打印机设备");
        }

    }

    private void connectByJugde(UsbManager manager, String devicename) {
        closeport();
        //通过USB设备名找到USB设备
        UsbDevice usbDevice = Utils.getUsbDeviceFromName(devicename);
        //判断USB设备是否有权限
        if (manager.hasPermission(usbDevice)) {
            usbConn(usbDevice);
        } else {//请求权限
            PendingIntent pendingIntent = PendingIntent.getBroadcast(Tools.getApplicationByReflect(), 0, new Intent(ACTION_USB_PERMISSION), 0);
            manager.requestPermission(usbDevice, pendingIntent);
        }
    }

    /**
     * usb连接
     *
     * @param usbDevice usb设备
     */
    private void usbConn(UsbDevice usbDevice) {
        new DeviceConnFactoryManager.Build()
                .setId(0)
                .setConnMethod(DeviceConnFactoryManager.CONN_METHOD.USB)
                .setUsbDevice(usbDevice)
                .setContext(Tools.getApplicationByReflect())
                .build();
        DeviceConnFactoryManager.getDeviceConnFactoryManagers()[0].openPort();
    }


    private BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            switch (action) {
                //USB请求访问权限
                case ACTION_USB_PERMISSION:
                    synchronized (this) {
                        UsbDevice device = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                        if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                            if (device != null) {//用户点击授权
                                usbConn(device);
                            }
                        } else {//用户点击不授权,则无权限访问USB
                            LogUtils.e("No access to USB");
                        }
                    }
                    break;
                //Usb连接断开广播
                case ACTION_USB_DEVICE_DETACHED:
                    UsbDevice usbDevice = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (usbDevice != null && usbDevice.equals(DeviceConnFactoryManager.getDeviceConnFactoryManagers()[0].usbDevice())) {
                        mHandler.obtainMessage(CONN_STATE_DISCONN).sendToTarget();
                    }
                    break;
                //连接状态
                case DeviceConnFactoryManager.ACTION_CONN_STATE:
                    int state = intent.getIntExtra(DeviceConnFactoryManager.STATE, -1);
                    int deviceId = intent.getIntExtra(DeviceConnFactoryManager.DEVICE_ID, -1);
                    switch (state) {
                        case DeviceConnFactoryManager.CONN_STATE_DISCONNECT:
                            if (id == deviceId) {
                                LogUtils.d("设备已经断开");
                            }
                            break;
                        case DeviceConnFactoryManager.CONN_STATE_CONNECTING:
                            LogUtils.d("设备连接中....");
                            break;
                        case DeviceConnFactoryManager.CONN_STATE_CONNECTED:
                            LogUtils.d("设备已连接");
//                            connectPrintDevice();
                            break;
                        case CONN_STATE_FAILED:
                            LogUtils.d("设备连接失败");
                            break;
                        default:
                            break;
                    }
                    break;

                default:
                    break;
            }
        }
    };


    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case CONN_STATE_DISCONN://断开连接
                    DeviceConnFactoryManager deviceConnFactoryManager = DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id];
                    if (deviceConnFactoryManager != null && deviceConnFactoryManager.getConnState()) {
                        DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].closePort(id);
                        ToastUtils.showShort(getString(R.string.str_disconnect_success));
                    }
                    break;
                case PRINTER_COMMAND_ERROR://打印机指令错误
                    ToastUtils.showShort(R.string.str_choice_printer_command);
                    break;
                case CONN_PRINTER://未连接打印机
                    ToastUtils.showShort(getString(R.string.str_cann_printer));
                    break;

                case Constant.tip:
                    String str = (String) msg.obj;
                    ToastUtils.showShort(str);
                    break;
                default:
                    break;
            }
        }
    };

    public void print(final JhResultBean jhResultBean, final String queueBusiness) {
        if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id] == null || !DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getConnState()) {
            ToastUtils.showShort(R.string.str_cann_printer);
            return;
        }
        if (threadPool == null) {
            threadPool = ThreadPool.getInstantiation();
        }
        threadPool.addSerialTask(new Runnable() {
            @Override
            public void run() {
                if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getCurrentPrinterCommand() == PrinterCommand.ESC) {
                    DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].sendDataImmediately(PrintContent.getReceipt(jhResultBean, queueBusiness));
                } else {
                    mHandler.obtainMessage(PRINTER_COMMAND_ERROR).sendToTarget();
                }
            }
        });
    }

    public void obtainPrintDeviceStatus() {
        //打印机状态查询
        if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id] == null ||
                !DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getConnState()) {
            ToastUtils.showShort(getString(R.string.str_cann_printer));
            return;
        }
        ThreadPool.getInstantiation().addSerialTask(new Runnable() {
            @Override
            public void run() {
                if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getCurrentPrinterCommand() == PrinterCommand.ESC) {
                    DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].sendByteDataImmediately(esc);
                } else if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getCurrentPrinterCommand() == PrinterCommand.TSC) {
                    DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].sendByteDataImmediately(tsc);
                } else if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getCurrentPrinterCommand() == PrinterCommand.CPCL) {
                    DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].sendByteDataImmediately(cpcl);
                }
            }
        });
    }

    public void disconnectDevice() {
        if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id] == null || !DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].getConnState()) {
            ToastUtils.showShort(R.string.str_cann_printer);
            return;
        }
        mHandler.obtainMessage(CONN_STATE_DISCONN).sendToTarget();
    }

    public void unregisterBroadCast(Context context) {
        if (isRegister) {
            isRegister = false;
            context.unregisterReceiver(receiver);

        }
        if (manager != null) {
            manager = null;
        }
        disconnectDevice();
        DeviceConnFactoryManager.closeAllPort();
        if (mHandler != null) {
            mHandler.removeCallbacksAndMessages(null);
            mHandler = null;
        }
        if (threadPool != null) {
            threadPool.stopThreadPool();
        }

        if (executorService != null) {
            executorService.shutdown();
            executorService = null;
        }
    }

    /**
     * 重新连接回收上次连接的对象，避免内存泄漏
     */
    private void closeport() {
        if (DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id] != null && DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].mPort != null) {
            DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].reader.cancel();
            DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].mPort.closePort();
            DeviceConnFactoryManager.getDeviceConnFactoryManagers()[id].mPort = null;
        }
    }
}
